package com.sc.nft.entity.vo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.sc.nft.entity.EcologyPool;
import com.sc.nft.entity.UserAssets;
import com.sc.nft.entity.UserCollection;
import com.sc.nft.entity.UserEquityProps;
import com.sc.nft.enums.BoxConditionEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.stream.Collectors;

@Data
public class WhetherUserMeetsRedemptionConditionsVO {

    @ApiModelProperty("兑换数量")
    private Integer sum;

    @ApiModelProperty("兑换条件")
    private List<QueryBoxConditionVO> queryBoxConditions;


    @ApiModelProperty("用户碎片")
    private UserAssets userAssets;

    @ApiModelProperty("用户的权益道具")
    private List<UserEquityProps> userEquityProps;

    @ApiModelProperty("用户持有的藏品")
    private List<UserCollection> collections;

    @ApiModelProperty("用户持有积分")
    private EcologyPool ecologyPool;

    /**
     * 获取兑换条件中的满足权益道具的条件 权益道具ID
     *
     * @return
     */
    public List<Long> getEquityPropsIds() {
        return this.queryBoxConditions.stream().filter(queryBoxConditionVO -> queryBoxConditionVO.getType().equals(2) && queryBoxConditionVO.getConversionType().equals(BoxConditionEnum.EQUITY_PROPS)).map(QueryBoxConditionVO::getTripartiteId).collect(Collectors.toList());
    }

    /**
     * 获取是否需要持有NFT才可以兑换
     *
     * @return
     */
    public QueryBoxConditionVO getCollectionResult() {
        List<QueryBoxConditionVO> collect = this.queryBoxConditions.stream().filter(queryWebBoxConditionVO -> queryWebBoxConditionVO.getType().equals(1)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            return collect.get(0);
        }
        return null;
    }

    /**
     * 获取积分所需id
     *
     * @return
     */
    public Boolean whetherFragmentsAreNeeded() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.STAR_FRAGMENT);
        return CollUtil.isNotEmpty(screen);
    }

    /**
     * 获取权益道具所需id
     *
     * @return
     */
    public Boolean whetherEquityPropsAreNeeded() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.EQUITY_PROPS);
        return CollUtil.isNotEmpty(screen);
    }


    /**
     * 判断是否需要生态积分
     *
     * @return
     */
    public Boolean whetherEcologyPoolPointsNeeded() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.ECOLOGY_POOL_POINTS);
        return CollUtil.isNotEmpty(screen);
    }

    /**
     * 验证. 是否满足全部条件
     *
     * @return
     */
    public Boolean comparison() {
        // 验证碎片是否足够
        Boolean debrisVerify = debrisVerify();
        // nft验证
        Boolean nftVerify = nftVerify();

        // 权益道具验证
        Boolean equityPropVerify = equityPropVerify();

        //验证生态积分
        Boolean ecologyPoolVerify = ecologyPoolVerify();

        // 三者全部满足,返回true
        if (debrisVerify && nftVerify && equityPropVerify && ecologyPoolVerify) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


    public List<QueryBoxConditionVO> screen(Integer type, BoxConditionEnum boxConditionEnum) {
        return this.queryBoxConditions.stream().filter(queryBoxConditionVO -> queryBoxConditionVO.getType().equals(type) && queryBoxConditionVO.getConversionType().equals(boxConditionEnum)).collect(Collectors.toList());
    }

    public List<QueryBoxConditionVO> screen(Integer type) {
        return this.queryBoxConditions.stream().filter(queryBoxConditionVO -> queryBoxConditionVO.getType().equals(type)).collect(Collectors.toList());
    }


    /**
     * 碎片验证
     * 当条件中存在.但是结果不存在,直接返回False
     *
     * @return
     */
    public Boolean debrisVerify() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.STAR_FRAGMENT);
        BigDecimal debris = BigDecimal.ZERO;
        if (CollUtil.isEmpty(screen)) {
            return Boolean.TRUE;
        }

        if (BeanUtil.isEmpty(this.userAssets)) {
            return Boolean.FALSE;
        }
        // 获取所有碎片,目前只有一个 但是要防止他配置多个相同的碎片(张治沛绝对干的出来这种蠢事)
        for (QueryBoxConditionVO queryBoxConditionVO : screen) {
            debris = debris.add(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()));
        }

        // 兑换所需要的所有碎片
        BigDecimal userDebrisSum = debris.multiply(Convert.toBigDecimal(this.sum));

        // 用户碎片
        BigDecimal userDebris = this.userAssets.getTokenNum();
        if (NumberUtil.isGreaterOrEqual(userDebris, userDebrisSum)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 用户nft验证
     * nft目前只验证一个.不考虑验证多个的问题.
     * 当条件中存在.但是结果不存在,直接返回False
     *
     * @return
     */
    public Boolean nftVerify() {
        List<QueryBoxConditionVO> screen = screen(1);
        Boolean satisfy = Boolean.TRUE;
        if (CollUtil.isEmpty(screen)) {
            return satisfy;
        }
        if (CollUtil.isEmpty(this.collections)) {
            return Boolean.FALSE;
        }
        for (QueryBoxConditionVO queryBoxConditionVO : screen) {
            List<UserCollection> exist = collections.stream().filter(userCollection -> userCollection.getCollectionId().equals(queryBoxConditionVO.getTripartiteId())).collect(Collectors.toList());
            if (CollUtil.isEmpty(exist)) {
                satisfy = Boolean.FALSE;
                break;
            }
        }
        return satisfy;
    }


    /**
     * 权益道具验证
     * 当条件中存在.但是结果不存在,直接返回False
     *
     * @return
     */
    public Boolean equityPropVerify() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.EQUITY_PROPS);
        // 是否满足要求
        Boolean satisfy = Boolean.TRUE;
        if (CollUtil.isEmpty(screen)) {
            return satisfy;
        }

        if (CollUtil.isEmpty(this.userEquityProps)) {
            return Boolean.FALSE;
        }

        for (QueryBoxConditionVO queryBoxConditionVO : screen) {
            // 权益道具不会出现小数点.
            Integer costSum = Convert.toInt(queryBoxConditionVO.getCostQuantity());
            // 权益道具id
            Long tripartiteId = queryBoxConditionVO.getTripartiteId();
            // 拥有的权益道具数量
            List<UserEquityProps> possess = userEquityProps.stream().filter(equityProps -> equityProps.getEquityPropsId().equals(tripartiteId)).collect(Collectors.toList());
            // 为空直接结束,因为不满足
            if (CollUtil.isEmpty(possess)) {
                return satisfy;
            }
            // 需要的权益道具数量
            Integer needSum = costSum * this.sum;

            // 拥有的数量
            if (possess.size() < needSum) {
                satisfy = Boolean.FALSE;
                break;
            }
        }
        return satisfy;
    }

    /**
     * 生态积分验证
     *
     * @return
     */
    public Boolean ecologyPoolVerify() {
        List<QueryBoxConditionVO> screen = screen(2, BoxConditionEnum.ECOLOGY_POOL_POINTS);
        if (CollUtil.isEmpty(screen)) {
            return Boolean.TRUE;
        }
        if (Objects.isNull(this.ecologyPool)) {
            return Boolean.FALSE;
        }
        BigDecimal debris = BigDecimal.ZERO;
        // 获取所有生态积分
        for (QueryBoxConditionVO queryBoxConditionVO : screen) {
            debris = debris.add(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()));
        }
        // 兑换所需要的所有积分
        BigDecimal userDebrisSum = debris.multiply(Convert.toBigDecimal(this.sum));
        // 生态积分
        BigDecimal userDebris = this.ecologyPool.getLinkCount();
        if (NumberUtil.isGreaterOrEqual(userDebris, userDebrisSum)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public String exchangeMix() {
        StringJoiner stringJoiner = new StringJoiner(",");
        queryBoxConditions.forEach(queryBoxConditionVO -> {
            String format = "";
            if (queryBoxConditionVO.getType().equals(1)) {
                format = StrUtil.format("持有NFT:{}", queryBoxConditionVO.getName());
            } else {
                format = StrUtil.format("使用{}*{}", queryBoxConditionVO.getName(), queryBoxConditionVO.getCostQuantity());
            }
            stringJoiner.add(format);
        });
        return stringJoiner.toString();
    }

}
